


#ifndef __DRV_NETWORK_H__
#define __DRV_NETWORK_H__


#include "config.h"
#include "app_config.h"
#include "drv_jiffes.h"


#if (TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G)||(TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB)

#define NET_POWER_ON()          // 网络模块供电ON
#define NET_POWER_OFF()         // 网络模块供电OFF
#define NET_RST_HIGH()          // 网络模块复位脚HIGH
#define NET_RST_LOW()           // 网络模块复位脚LOW
#define CAT1_PWRKEY_HIGH()      // 4G模块 PWRKEY HIGH
#define CAT1_PWRKEY_LOW()       // 4G模块 PWRKEY LOW

enum {
    E_MQTT_DISCONNECTED = 0,
    E_MQTT_CONNECTED = 1,
};


/**
 * @brief   AT命令返回码值
*/
enum {
    AT_SUCCESS=0,   // 成功
    AT_TIMEOUT,     // 超时
    AT_NORECV, 
    AT_WAITING,     
    AT_ERROR,
};

enum {
    AT_STATUS_IDLE=0,   /* 空闲状态 */
    AT_STATUS_SENDING,  /* 正在发送数据 */
    AT_STATUS_WAITING,  /* 正在等待发送 */
};


enum {
    E_NET_MODULE_UNKNOW=0,  // 未知网络模块
    E_NET_MODULE_CAT1=1,    // 4G Cat1模块
    E_NET_MODULE_NBIOT=2,   // NB-iot模块
    E_NET_MODULE_MAX
};

/**
 * @brief   网络状态
 */
enum {
    E_NETSTA_UNKNOW=0,      // 未知网络状态
    E_NETSTA_CONNECTING,    // 正在连接网络
    E_NETSTA_CONNECTED,     // 网络已连接
    E_NETSTA_DISCONNECTED,  // 网络已断开
};

/**
 * @brief   网络模块PWRKEY操作步骤
 */
enum {
    E_NET_PWRKEY_STEP_INIT=0,
    E_NET_PWRKEY_STEP_L,
    E_NET_PWRKEY_STEP_H,
    E_NET_PWRKEY_STEP_MAX
};


enum {
    E_NET_INIT_STEP_0=0,
    E_NET_INIT_STEP_1,
    E_NET_INIT_STEP_2,
    E_NET_INIT_STEP_3,
    E_NET_INIT_STEP_4,
    E_NET_INIT_STEP_5,
    E_NET_INIT_STEP_MAX,
};


/**
 * @brief   AT命令ID
 */
typedef enum {
    ATCMD_ID_UNKNOW=0,    // 无效命令

// TODO: 4G CAT1模块AT命令ID
    ATCMD_ID_4G_CPIN,         // +CPIN: READY
    ATCMD_ID_4G_CSQ,          // +CSQ: 22,99
    ATCMD_ID_4G_CPSI,         // +CPSI: LTE,Online,460-00,0x252C,220581203,5,EUTRAN-BAND39,38544,3,0,30,51,44,14
    ATCMD_ID_4G_CGREG,        // +CGREG: 0,1
    ATCMD_ID_4G_SIMEI,        //
    ATCMD_ID_4G_CICCID,       //

    ATCMD_ID_4G_CRESET,       // 4G模块 复位
    ATCMD_ID_4G_CPOF,         // 4G模块 关机
    ATCMD_ID_4G_CTZU_GET,     // 查询 Automatic time and time zone update 
    ATCMD_ID_4G_CTZU_SET,     // 设置 Automatic time and time zone update 
    ATCMD_ID_4G_CCLK,         // 获取 日期时间

    ATCMD_ID_4G_CFUNC,       // 飞行模式

    ATCMD_ID_4G_CMQTTSTART,
    ATCMD_ID_4G_CMQTTACCQ,
    ATCMD_ID_4G_CMQTTCFG_VER,
    ATCMD_ID_4G_CMQTTCFG_ARG,
    ATCMD_ID_4G_CMQTTCONNECT,
    ATCMD_ID_4G_CMQTTSUB,
    ATCMD_ID_4G_CMQTTPAYLOAD,
    ATCMD_ID_4G_PAYLOAD_DATA,
    ATCMD_ID_4G_CMQTTPUB,

// TODO: NB-iot模块AT命令ID
    ATCMD_ID_NB_CIMI,
    ATCMD_ID_NB_NCCID,
    ATCMD_ID_NB_CGSN,
    ATCMD_ID_NB_CGATT,
    ATCMD_ID_NB_FASTOFF,
    ATCMD_ID_NB_CPSMS,
    ATCMD_ID_NB_CPSMS_GET,
    ATCMD_ID_NB_CGMR,
    ATCMD_ID_NB_CEREG,
    ATCMD_ID_NB_CESQ,
    ATCMD_ID_NB_CSQ,
    ATCMD_ID_NB_CCLK,

    ATCMD_ID_NB_MQNEW,
    ATCMD_ID_NB_MQCON,
    ATCMD_ID_NB_MQSUB,
    ATCMD_ID_NB_MQPUB,
    ATCMD_ID_NB_MQUNSUB,
    ATCMD_ID_NB_MQDISCON,
    ATCMD_ID_MAX,
}atcmd_id_t;


// TODO: AT 命令字符串定义
// TODO: 4G CAT1模块AT命令字符串=================================================================================
#define ATCMD_STR_4G_CPIN         "AT+CPIN?\r\n"      // SIM卡插入检测
#define ATCMD_STR_4G_CSQ          "AT+CSQ\r\n"        // 查询信号质量
// #define ATCMD_STR_4G_CPSI         "AT+CPSI?\r\n"      // 查询UE系统信息
#define ATCMD_STR_4G_CGREG        "AT+CGREG?\r\n"     // 网络注册状态
#define ATCMD_STR_4G_SIMEI        "AT+SIMEI?\r\n"     // 模块IMEI号查询
#define ATCMD_STR_4G_CICCID       "AT+CICCID\r\n"     // SIM卡号查询

#define ATCMD_STR_4G_CRESET       "AT+CRESET\r\n"     // 4G模块 复位
#define ATCMD_STR_4G_CPOF         "AT+CPOF\r\n"       // 4G模块 关机
#define ATCMD_STR_4G_CTZU_GET     "AT+CTZU?\r\n"      // 查询 Automatic time and time zone update 
#define ATCMD_STR_4G_CTZU_SET     "AT+CTZU=%d\r\n"     // 设置 Automatic time and time zone update 
#define ATCMD_STR_4G_CCLK         "AT+CCLK?\r\n" 

// #define ATCMD_STR_4G_CFUN         "AT+CFUN=%d\r\n"     // 0:飞行模式 1:正常模式


// MQTT 相关命令
#define ATCMD_STR_4G_CMQTTSTART       "AT+CMQTTSTART\r\n"                 // 启动MQTT服务
#define ATCMD_STR_4G_CMQTTACCQ        "AT+CMQTTACCQ=0,\"%s\",0\r\n"       // AT+CMQTTACCQ=0,"864423065869610@899qc0",0\r\n
#define ATCMD_STR_4G_CMQTTCFG_VER     "AT+CMQTTCFG=\"version\",0,4\r\n"   
#define ATCMD_STR_4G_CMQTTCFG_ARG     "AT+CMQTTCFG=\"argtopic\",0,1,1\r\n"
#define ATCMD_STR_4G_CMQTTCONNECT     "AT+CMQTTCONNECT=0,\"%s\",60,1,\"%s\",\"%s\"\r\n" // host:port  user  password
#define ATCMD_STR_4G_CMQTTSUB         "AT+CMQTTSUB=0,\"%s\",%d\r\n"    // sub topic
#define ATCMD_STR_4G_CMQTTPAYLOAD     "AT+CMQTTPAYLOAD=0,%d\r\n"      // payload len
#define ATCMD_STR_4G_CMQTTPUB         "AT+CMQTTPUB=0,\"%s\",%d\r\n"    // pub topic


// TODO: NB-iot模块AT命令字符串=================================================================================
// #define ATCMD_STR_NB_FASTOFF            "AT+FASTOFF\r\n"    // 快速关机
#define ATCMD_STR_NB_CPSMS              "AT+CPSMS=%d\r\n"   // PSM设置
#define ATCMD_STR_NB_CPSMS_GET          "AT+CPSMS?\r\n"     // 查询PSM设置
#define ATCMD_STR_NB_CGMR               "AT+CGMR\r\n"       // 查询软件版本
#define ATCMD_STR_NB_CIMI               "AT+CIMI\r\n"       // 用于查询 USIM 卡的 IMSI 值
#define ATCMD_STR_NB_NCCID              "AT+NCCID\r\n"       // 用于查询USIM卡ID号码 ICCID 卡的
#define ATCMD_STR_NB_CGSN               "AT+CGSN=%d\r\n"    // 0:SN,1:IMEI,2:IMEISV,3:SVN
// #define ATCMD_STR_NB_CGATT              "AT+CGATT?\r\n"     // 
#define ATCMD_STR_NB_CERGE              "AT+CEREG?\r\n"
#define ATCMD_STR_NB_CESQ               "AT+CESQ\r\n"
#define ATCMD_STR_NB_CSQ                "AT+CSQ\r\n"
#define ATCMD_STR_NB_CCLK               "AT+CCLK?\r\n"            

#define ATCMD_STR_NB_MQNEW              "AT+MQNEW=%s,%s,%d,%d\r\n"  // AT+MQNEW=899qc0.cn1.mqtt.chat,1883,5000,200\r\n
#define ATCMD_STR_NB_MQCON              "AT+MQCON=0,4,\"%s\",%d,1,1,\"%s\",%d,0,2,\"%s\",\"%s\",\"%s\"\r\n"
#define ATCMD_STR_NB_MQSUB              "AT+MQSUB=0,\"%s\",%d\r\n"
#define ATCMD_STR_NB_MQPUB              "AT+MQPUB=0,\"%s\",%d,0,0,%d,%s\r\n"
                                        // <mqtt_id>：整型，MQTT id, AT+MQNEW 命令的返回值。
                                        // <topic>：字符串，发布消息的主题。
                                        // <QoS>：整型，消息的 QoS, 0, 1 或者 2。
                                        // <retained>：整型，保留标志,0 或者 1(0：不保留消息。1：表示是保留消息)。
                                        // <dup>：整型，重复标志， 0 或者 1（0：第一次发送；1 重复发送）。
                                        // <message_len>：整型，发布消息的长度，按照字节计算,范围：1-1000byte(s)。
                                        // <message>：字符串，发布消息内容，采用十六进制字符串格式。
#define ATCMD_STR_NB_MQUNSUB            "AT+MQUNSUB=%d,\"%s\"\r\n"
#define ATCMD_STR_NB_MQDISCON           "AT+MQDISCON=%d\r\n"



struct at_data_t {
    uint32_t timeout;           /* 发送等待超时时间 */
    uint32_t delay;             /* 本条AT命令发送延时多久才能发送下一条AT命令 */
    uint8_t cmd_id;             /* AT指令ID */
    uint8_t cmd_state;          /* AT指令状态 */
    uint8_t arg;                /* AT指令参数 */
    uint8_t trys;               /* AT命令发送失败，重试次数 */
    uint8_t success_str[16];     /* AT指令期望接收到的数据 */
    uint8_t response_str[16];   /* AT响应字符串，用于判断AT回复数据是哪一条AT命令的*/
};

#define AT_CMD_LIST_LEN     (20)    // AT命令队列长度
struct at_cmd_t {
    uint8_t size;       // 列表长度
    uint8_t status;     // AT 命令状态
    
    uint8_t action_idx; // AT 命令列表执行索引
    uint8_t append_idx; // AT 命令列表添加索引
    struct at_data_t list[AT_CMD_LIST_LEN];    // AT命令列表
};

#define D_AT_TXBUF_LEN      (256)       // AT指令接发送存大小
#define D_AT_RXBUF_LEN      (256)       // AT指令接收缓存大小
#define D_MQTTPAYLOAD_LEN   (256)       // MQTT payload缓存大小

struct network_t {
    uint8_t at_ready      ;    // 1：AT命令准备好，0：未准备好不能发送AT命令
    uint8_t simcardin     ;    // 1：SIM卡已插入，0：SIM卡未插入
    uint8_t mqtt_connected;    // 1: mqtt 已初始化
    uint8_t net_connecting;    // 1: 网络连接中
    uint8_t module_ctzu   ;    // 网络模块自动时区设置 1：自动时区，0：UTC时间
    uint8_t pwrkey_step   ;    // 4G 模块PWRKEY低脉冲步骤
    uint8_t init_step     ;    // 4G 模块初始化步骤
    uint8_t ctzu_state    ;    // 4G 自动时间时区更新设置

    uint8_t rssi_loss_cnt;          // RSSI 信号弱计数
    uint8_t mqtt_senderr_cnt;       // MQTT发送数据失败计数

//  网络状态
    int rssi;   // 10~31 越大信号质量越好
    int ber;    // 0~99 误码率，99网络就不能用了
    int reg_mode;   // mode:分别是 0 or 1 or 2,  其中:
                    //      0 ：代表关闭网络注册结果码, 
                    //      1 ：代表当网络注册状态改变时激活网络注册结果码, 
                    //      2 ：代表激活网络注册结果码同时显示区域和小区信息.
    int reg_stat;   // stat:返回值共有三个,分别是 0, 1, 2,3,4,5 ,  其中
                    //      0 : 代表没有注册网络同时模块没有找到运营商, 
                    //      1 : 代注册到了本地网络, 
                    //      2 : 代表找到运营商但没有注册网络, 
                    //      3 : 代表注册被拒绝, 
                    //      4 : 代表未知的数据, 
                    //      5 :代表注册在漫游状态.
    int gatt;       //  GATT:1附着成功，0：去附着
    
    uint8_t simei[16];  // IMEI号 国际移动设备识别码 （International Mobile Equipment Identity）。
                        // 由15位数字组成，全球唯一ID，用来区别每一部移动通信设备。与手机是绑定关系。
                        // 第一部分 TAC，Type Allocation Code，类型分配码。86为中国。
                        // 其余的部分没啥有用信息。
                        // 典型IMEI码：868540050954128

    uint8_t simsi[16];  // IMSI号 国际移动用户识别号。（International Mobile Subscriber Identification Number）
                        // 由15位数字组成，全球唯一ID，用来区别每一位移动用户。与SIM卡是绑定关系。
                        // 第一部分：MCC，移动国家代码 （Mobile Country Code）。3位，中国为460。
                        // 第二部分：MNC，移动网络代码（Mobile Network Code）。2位，中国移动使用00、02、04、07，中国联通GSM系统使用01、06、09，中国电信CDMA系统使用03、05，电信4G使用11，中国铁通使用20。（百度上是这么说的，可我的移动物联卡是08…啊这 (⊙?⊙) … ）
                        // 第三部分：MSIN，移动订阅用户识别代码（Mobile subscription identification number）。10位。
                        // 典型IMSI码：460080585306741

    uint8_t ciccid[32]; // SIM卡号 ICCID：集成电路卡识别码（Integrate circuit card identity）。
                        // 由20位数字组成，是IC卡的唯一识别号码。与SIM卡是绑定关系。
                        // 前六位为运营商代码：
                        // 中国移动的为：898600；898602；898604；898607 。
                        // 中国联通的为：898601；898606；898609。
                        // 中国电信的为：898603。
                        // 其余的部分没啥有用信息。
                        // 典型ICCID码: 89860485192072216741


    int     retcode;
    int     recvlen;
    uint8_t msg_type;                   /*消息类型*/
    uint8_t opt_type;                   /*操作类型：1阈值同步，2阈值设置 */
    uint8_t recv_subtopic[64];

    int32_t recv_diff;                  /* 接收时间偏差 */
    uint32_t recv_timeout;              /* 接收超时时间 */
    jiffes_t recv_starttime;            /* 接收开始时间 */
    jiffes_t jsendtime;                 /* 命令发送超时 */
    jiffes_t jpwrkeytime;               /* 4G PWRKEY 时间*/
    jiffes_t jdevinit;                  /* 设备初始化时间 */
    jiffes_t jnetrst;                   /* 网络模块复位时间 */

    struct at_cmd_t atcmd;              /* AT命令列表 */
    
    // TODO: AT CMD串口收发相关
    int rxlen;                          /* 接收数据长度 */
    uint8_t rxbuf[D_AT_RXBUF_LEN];      /* 接收数据缓存 */
    int txlen;                          /* 发送数据长度 */
    uint8_t txbuf[D_AT_TXBUF_LEN];      /* 发送数据缓存 */
    int payload_len;                    /* Payload len*/
    uint8_t payload_buf[D_MQTTPAYLOAD_LEN];           /* Payload buffer*/
};
void network_module_init(struct app_t* app);

void network_atcmd_list_clear(struct app_t* app);

void network_atcmd_process_task(struct app_t* app);


#if TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G
// 4G cat.1模块
void cat1_ctzu_get_atcmd_send(struct app_t* app);

void cat1_ctzu_set_atcmd_send(struct app_t* app, uint8_t arg);

void cat1_network_check_atcmd_send(struct app_t* app);

void cat1_mqtt_connect_atcmd_send(struct app_t* app);

void cat1_mqtt_report_atcmd_send(struct app_t* app);

void cat1_poweroff_atcmd_send(struct app_t* app);

void cat1_cfunc_atcmd_send(struct app_t* app, uint8_t arg);

#elif TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB

// TODO: NB-Iot============================================

void nbiot_network_check_atcmd_send(struct app_t* app);

void nbiot_mqtt_connect_atcmd_send(struct app_t* app);

void nbiot_module_info_get(struct app_t* app);

void nbiot_poweroff_atcmd_send(struct app_t* app);

void nbiot_psmmode_atcmd_send(struct app_t* app, uint8_t psmmode);

#ifdef ATCMD_STR_NB_CPSMS_GET
void nbiot_psmmode_get_atcmd_send(struct app_t* app);
#endif

#endif

void network_checking_reconnect(struct app_t* app);

void network_server_reconnect(struct app_t* app);

void network_mqtt_report_atcmd_send(struct app_t* app, uint8_t msg_type);

void rtc_sync_cclk_set_atcmd_send(struct app_t* app);

void network_module_version(struct app_t* app);

void network_mqtt_connect_atcion(struct app_t* app);

#endif
#endif // __CAT1_H__
